//
//  WorldTreeModel.cpp
//  Editor
//
//  Created by Jeppe Nielsen on 11/6/14.
//  Copyright (c) 2014 Jeppe Nielsen. All rights reserved.
//

#include "WorldTreeModel.hpp"
#include <QtCore/QMimeData>
#include <iostream>
#include "GameObject.hpp"

using namespace Qt;

WorldTreeModel::WorldTreeModel(QObject *parent) : QAbstractItemModel(parent) {
    world = 0;
}

WorldTreeModel::~WorldTreeModel() { }

void WorldTreeModel::SetWorld(GameWorld *world) {
    this->world = world;
}

int WorldTreeModel::columnCount(const QModelIndex &parent) const
{
    if (parent.isValid())
        return 1;//static_cast<TreeItem*>(parent.internalPointer())->columnCount();
    else
        return 1;
}

QVariant WorldTreeModel::data(const QModelIndex &index, int role) const {
    if (!index.isValid())
        return QVariant();

    if (role != Qt::DisplayRole)
        return QVariant();

    //TreeItem *item = static_cast<TreeItem*>(index.internalPointer());

    return "GameObject";//item->data(index.column());
}

Qt::ItemFlags WorldTreeModel::flags(const QModelIndex &index) const {
    //if (!index.isValid())
    //    return 0;
    
    Qt::ItemFlags defaultFlags = QAbstractItemModel::flags(index);

     if (index.isValid())
         return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags;
     else
         return Qt::ItemIsDropEnabled | defaultFlags;
    

    //return QAbstractItemModel::flags(index);
}

QVariant WorldTreeModel::headerData(int section, Qt::Orientation orientation, int role) const {
    if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
        return "Name";//rootItem->data(section);

    return QVariant();
}

QModelIndex WorldTreeModel::index(int row, int column, const QModelIndex &parent) const {
    if (!world) {
        return QModelIndex();
    }

    if (!hasIndex(row, column, parent))
        return QModelIndex();
    
    
    if (!parent.isValid()) {
        int counter = 0;
        for (int i=0; i<world->Objects().size(); i++) {
            if (!world->Objects()[i]->Parent) {
                if (counter == row) {
                    return createIndex(row, column, world->Objects()[i]);
                }
                counter++;
            }
        }
        return QModelIndex();
    } else {
        GameObject* object = static_cast<GameObject*>(parent.internalPointer());
        return createIndex(row, column, object->Children()[row]);
    }
    return QModelIndex();
}

QModelIndex WorldTreeModel::parent(const QModelIndex &index) const
{
    if (!index.isValid() || !world)
        return QModelIndex();
    
    GameObject* object = static_cast<GameObject*>(index.internalPointer());
    
    if (!object->Parent) {
        return QModelIndex();
    } else {
        GameObject* parent = object->Parent;
        for (int i=0; i<parent->Children().size(); i++) {
            if (parent->Children()[i] == object) {
                return createIndex(i, 0, parent);
            }
        }
    }
    
    return QModelIndex();
}

int WorldTreeModel::rowCount(const QModelIndex &parent) const
{
    if (parent.column()>0 || !world) {
        return 0;
    }

    if (!parent.isValid()) {
        int objects = 0;
        for (int i=0; i<world->Objects().size(); i++) {
            if (!world->Objects()[i]->Parent) {
                objects++;
            }
        }
        return objects;
    } else {
        GameObject* object = static_cast<GameObject*>(parent.internalPointer());
        return (int)object->Children().size();
    }
}


Qt::DropActions WorldTreeModel::supportedDropActions() const {
     return Qt::MoveAction; //Qt::CopyAction | Qt::MoveAction;
}

static QModelIndex sourceObjectChanged;

bool WorldTreeModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) {
     if (action == Qt::IgnoreAction)
         return true;
    
    if (!data->hasFormat("application/x-qabstractitemmodeldatalist")) {
        return false;
    }
    /*
    auto list = data->formats();
    
    for (int i=0; i<list.size(); i++) {
        std::cout<<list[i].toStdString() << std::endl;
    }
    */
    
    
    QByteArray encoded = data->data("application/x-qabstractitemmodeldatalist");
    QDataStream stream(&encoded, QIODevice::ReadOnly);
 
    int objectIndex = 0;
    while (!stream.atEnd()) {
        stream >> objectIndex;
    }
    
    if (objectIndex<0) return false;
    if (objectIndex>=world->Objects().size()) return false;
    
    
    GameObject* gameObject = world->Objects()[objectIndex];
    
    emit layoutChanged();
    
    if (!parent.isValid()) {
        gameObject->Parent = 0;
        emit dataChanged(sourceObjectChanged, sourceObjectChanged);
    } else {
        GameObject* parentObject = static_cast<GameObject*>(parent.internalPointer());
        gameObject->Parent = parentObject;
        emit dataChanged(sourceObjectChanged, sourceObjectChanged);
        emit dataChanged(parent, parent);
    }
    
    return true;
}

QMimeData* WorldTreeModel::mimeData(const QModelIndexList &indexes) const
 {
     QMimeData *mimeData = new QMimeData();
     QByteArray encodedData;

     QDataStream stream(&encodedData, QIODevice::WriteOnly);
     
     foreach (QModelIndex index, indexes) {
         if (index.isValid()) {
            sourceObjectChanged = index;
            GameObject* object = static_cast<GameObject*>(index.internalPointer());
            int objectIndex = 0;
            for (int i=0; i<world->Objects().size(); i++) {
                if (object == world->Objects()[i]) {
                    objectIndex = i;
                    break;
                }
            }
         
            stream << objectIndex;
         }
     }

     mimeData->setData("application/x-qabstractitemmodeldatalist", encodedData);
     return mimeData;
 }


